﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Interfaces;
using AForge.Genetic;
using AForge.Math.Random;
using dto;
using AForge;

namespace Model
{
    public class Model :IModel
    {
       public Population Pop;
       private IController controller;
        private int MaxGenerations;

        

        public Model(int populationSize, int maxGenerations, dto.Selection globaldtoSelection, dto.Crossover globaldtoCrossover, 
            dto.FitnessFunktion globaldtoFitnessFunktion, dto.ChromosomType globaldtoChromosomType, double MutationRate, bool GenerationDependance,double crossoverrate, int chromosomesize)
       {
           this.MaxGenerations = maxGenerations;

           IChromosome ancestor = ancestor = new myDoubleArrayChromosome(new StandardGenerator(), new StandardGenerator(), new StandardGenerator(), chromosomesize);
           IFitnessFunction fitnessFunction = new doubleAckleyFct() ;
           ISelectionMethod selectionMethod = new EliteSelection();
           Range Bereich = new Range(-500, 500);

           switch (globaldtoSelection)
           {
               case Selection.Deterministic: { selectionMethod = new EliteSelection(); } break;
               case Selection.RouletteWheel : {selectionMethod= new RouletteWheelSelection(); } break;
               case Selection.Rank: { selectionMethod = new RankSelection(); } break;
               case Selection.Tournament : { } break;

           
           }

           switch (globaldtoCrossover)
           {
               case Crossover.OnePoint : { DrSommer.GetInstance().HowToDoIt = Crossover.OnePoint; } break;
               case Crossover.Template : { DrSommer.GetInstance().HowToDoIt = Crossover.Template; } break;
               case Crossover.TwoPoint : { DrSommer.GetInstance().HowToDoIt = Crossover.TwoPoint; } break;

           }

           switch (globaldtoFitnessFunktion)
           {
               case FitnessFunktion.Ackley: { fitnessFunction = new doubleAckleyFct(); Bereich = new Range(-20, 30); } break;
               case FitnessFunktion.CFunction: { fitnessFunction = new doubleCFunktionFct(); Bereich = new Range(-20,30); } break;
               case FitnessFunktion.Griewank: { fitnessFunction = new doubleGriewankFct(); Bereich = new Range(-512, 511); } break;
               case FitnessFunktion.NullValue: { fitnessFunction = new doubleNullValue(); } break;

           }

           switch (globaldtoChromosomType)
           {
               case ChromosomType.binary: { ancestor = new BinaryChromosome(32); fitnessFunction = new binaryAckleyFct(); } break;
               case ChromosomType.grey : { } break;
               case ChromosomType.real: { ancestor = new myDoubleArrayChromosome(new UniformGenerator(Bereich), new StandardGenerator(), new StandardGenerator(), chromosomesize); } break;
           }


           Pop = new Population(populationSize, ancestor, fitnessFunction, selectionMethod);
           Pop.MutationRate = MutationRate;
           Pop.CrossoverRate = crossoverrate;
       }
    
 void  IModel.MVC(IController controller)
{
    this.controller = controller;
}


void IModel.doEvolution()
{
    for (int i = 1; i <= MaxGenerations; i++)
    {
        if (i%100 == 0) 
        {
        controller.sendMessage(i + ". Generation:");
        controller.sendMessage("Best Fitness:" + System.Convert.ToString((1 / Pop.BestChromosome.Fitness)));
        controller.sendMessage("Best Chromosome:" + Pop.BestChromosome.ToString());
        controller.sendMessage("Average Fitness of the Population:" + System.Convert.ToString((1 / (Pop.FitnessAvg))));
        }
    //Pop.Crossover(); //BinaryChromosome
    Pop.RunEpoch();
    }
}

    }
}
